package com.zy.oauth.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.zy.common.core.constant.CacheConstants;
import com.zy.common.core.enums.ErrorEnums;
import com.zy.common.core.exception.BizException;
import com.zy.common.redis.RedisUtils;
import com.zy.common.utils.DateUtils;
import com.zy.common.utils.StringUtils;
import com.zy.common.utils.ip.IpUtils;
import com.zy.oauth.dto.AccountDto;
import com.zy.oauth.dto.pream.LoginPream;
import com.zy.oauth.entity.Account;
import com.zy.oauth.service.LoginService;
import com.zy.oauth.service.TokenService;
import com.zy.oauth.utils.AuthenticationContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import javax.validation.Valid;

/**
 * @author zy
 * @since 2023/3/20 21:26
 */
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private AuthenticationManager authenticationManager;

    // @Value("${verification.code.switch}")
    @Value("true")
    private Boolean VERIFICATION_CODE_SWITCH;

    @Override
    public String login(@Valid LoginPream pream) {
        // 验证码校验
        validateCaptcha(pream.getUsername(), pream.getCode(), pream.getUuid());
        // 登录前置校验
        loginPreCheck(pream.getUsername(), pream.getPassword());
        // 用户验证
        Authentication authentication = null;

        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(pream.getUsername(), pream.getPassword());
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);

        } catch (BadCredentialsException e) {
            throw new BizException(ErrorEnums.PASSWORD_IS_NOT_STANDARDIZED);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException(ErrorEnums.PASSWORD_IS_NOT_STANDARDIZED);
        } finally {
            AuthenticationContextHolder.clearContext();

        }
        AccountDto user = (AccountDto) authentication.getPrincipal();
//        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return tokenService.createToken(user);
    }


    /**
     * 登录前置校验
     *
     * @param username 用户名
     * @param password 用户密码
     */
    public void loginPreCheck(String username, String password) {
        log.info("username:{},password:{}", username, password);
    }

    /**
     * 校验验证码
     *
     * @param username 用户名
     * @param code     验证码
     * @param uuid     唯一标识
     * @return 结果
     */
    public void validateCaptcha(String username, String code, String uuid) {
        if (VERIFICATION_CODE_SWITCH) {
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
            String captcha = redisUtils.get(verifyKey);
            redisUtils.get(verifyKey);
            if (captcha == null) {
                throw new BizException(ErrorEnums.GET_VERIFICATION_CODE_LOSE_EFFICACY);
            }
            if (!code.equalsIgnoreCase(captcha)) {
                throw new BizException(ErrorEnums.GET_VERIFICATION_CODE_WRONG);
            }
        }
    }


    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(String userId) {
        Account account = new Account();
        account.setUserId(userId);
        account.setLoginIp(IpUtils.getIpAddr());
        account.setLoginAt(DateUtils.getNowDate());
        // userService.updateUserProfile(sysUser);
    }


}
